package caidan;

import caidan.res.Resource;
import com.github.crab2died.ExcelUtils;
import jinyilw.swing.SystemTools;
import jinyilw.swing.icon.LazyScaleIcon;
import jinyilw.common.Direction;
import jinyilw.common.Operator;
import jinyilw.common.SettingTools;
import jinyilw.common.TextTools;
import jinyilw.common.app.AppConfig;
import jinyilw.common.file.FileTools;
import jinyilw.swing.FontTools;
import jinyilw.swing.WindowTools;
import jinyilw.swing.rlaf.theme.UIData;
import jinyilw.swing.rlaf.utils.RBorderFactory;
import jinyilw.swing.rlaf.utils.RLafUtils;
import jinyilw.swing.visuals.Jcomp.TransRichButton;
import jinyilw.swing.visuals.Rcomp.RDialog;
import jinyilw.swing.visuals.Rcomp.RFileChooser;
import jinyilw.swing.visuals.Rcomp.ROptionPane;
import jinyilw.swing.visuals.comp.ActScaleImageComp;
import jinyilw.swing.visuals.comp.ScaleImageComp;
import jinyilw.swing.visuals.window.HintWindow;

import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

public class OneWeekView extends RDialog
{
	private static final long serialVersionUID = -1999806152240989657L;
	private final OneDayPanel[] days = new OneDayPanel[7];
	private final MainFrame owner;
	private Container container;
	private final TransRichButton saveText = new TransRichButton("导出文本");
	private final TransRichButton saveExcel = new TransRichButton("导出表格");
	private final TransRichButton enableEdit = new TransRichButton("启用食谱编辑功能");
	private TransRichButton openData;
	private TransRichButton saveData;
	private TransRichButton setRandomData;
	private final JPanel buttonPanel = new JPanel();
	final PositionConfiger positionConfiger = new PositionConfiger();
	private String saveStr;
	private boolean editable = false;
	private final Point ownerLocation = new Point();

	private MealLagerView mealLagerView;
	private BreakfastEditer breakfastEditer;
	private OtherMealEditer otherMealEditer;
	private SetRecipeDialog setRecipeDialog;

	Map<String, String> simpleExcelData = new HashMap<>();
	Map<String, String> customExcelData = new HashMap<>();

	public OneWeekView(MainFrame jf)
	{
		super(jf);
		owner = jf;
		init();
		addClosingOperater((Object o) ->
		{
			closeView();
		});
		ActScaleImageComp setComp = new ActScaleImageComp(
				(LazyScaleIcon) UIData.getDefaultUIData().frameUI.setIcon);
		setComp.addClickOperator((Object o) ->
		{
			if (setRecipeDialog == null)
				setRecipeDialog = new SetRecipeDialog(this, owner);
			setRecipeDialog.setLocationRelativeTo(this);
			setRecipeDialog.setVisible(true);
		});
		addActionComponent(setComp);
	}

	private void init()
	{
		setWindowSymbol(Resource.editIcon);
		setTitleHeight(30);
		setTitleFont(FontTools.getCustomFont(21));
		setTitleColor(Color.yellow);
		container = new Container();
		getContentPane().setLayout(null);
		getContentPane().add(container);
		container.setLayout(null);
		for (int i = 0; i < days.length; i++)
		{
			days[i] = new OneDayPanel(i, this);
			container.add(days[i]);
		}
		container.add(buttonPanel);
		buttonPanel.setLayout(null);
		buttonPanel.setBorder(RBorderFactory.getDefaultBorder());

		saveText.setForeground(Color.GREEN);
		saveText.setFont(FontTools.getCustomFont(18));
		buttonPanel.add(saveText);
		saveText.addClickOperater(new SaveOperator1());
		saveText.setImage(Resource.textIcon);

		saveExcel.setForeground(Color.GREEN);
		saveExcel.setFont(FontTools.getCustomFont(18));
		buttonPanel.add(saveExcel);
		saveExcel.addClickOperater(new SaveOperator3());
		saveExcel.setImage(Resource.excelIcon);

		enableEdit.setForeground(Color.red);
		enableEdit.setFont(FontTools.getCustomFont(17));
		buttonPanel.add(enableEdit);
		enableEdit.addClickOperater((Object o) ->
		{
			setEditable(true);
			setTitle("食 谱 编 辑");
		});

		buttonPanel.addMouseListener(new MouseAdapter()
		{
			@Override
			public void mouseClicked(MouseEvent e)
			{
				closeView();
				dispatchEvent(new WindowEvent(OneWeekView.this,
						WindowEvent.WINDOW_CLOSING));
			}
		});
		setDefaultDimensionRatio(0.97, 0.97);
		defaultSize();
	}

	public void showView()
	{
		ownerLocation.x = owner.getX();
		ownerLocation.y = owner.getY();
		if (!MainApp.isFullScreenMode)
			WindowTools.moveWindowToBorder(owner, Direction.DOWN);
		WindowTools.showWindowFromBorderToCenter(this, 30, Direction.UP);
	}

	private void closeView()
	{
		if (MainApp.getLagerView().isVisible())
			MainApp.getLagerView().dispose();
		WindowTools.moveWindowToBorder(this, Direction.LEFT);
		if (!MainApp.isFullScreenMode)
			WindowTools.showWindowFromBorder(owner, ownerLocation.x,
					ownerLocation.y, 30, Direction.DOWN);
	}

	public void setEditable(boolean editable)
	{
		if (this.editable == editable)
			return;
		this.editable = editable;
		if (editable)
		{
			if (openData == null)
			{
				Font font = FontTools.getCustomFont(18);
				openData = new TransRichButton("打开数据");
				saveData = new TransRichButton("保存数据");
				setRandomData = new TransRichButton("智能生成");
				openData.setForeground(Color.yellow);
				openData.setFont(font);
				openData.addClickOperater(new OpenDataOperator());
				// openData.setImagePath("appIco/open.png");
				saveData.setForeground(Color.yellow);
				saveData.setFont(font);
				saveData.addClickOperater(new SaveDataOperator());
				// saveData.setImagePath("appIco/save.png");
				setRandomData.setForeground(Color.yellow);
				setRandomData.setFont(font);
				setRandomData.addClickOperater((Object o) ->
				{
					setToRandom();
				});
			}
			buttonPanel.add(openData);
			buttonPanel.add(saveData);
			buttonPanel.add(setRandomData);
			buttonPanel.remove(enableEdit);
		} else
		{
			buttonPanel.add(enableEdit);
			if (openData != null)
			{
				buttonPanel.remove(openData);
				buttonPanel.remove(saveData);
				buttonPanel.remove(setRandomData);
			}
		}
		OneDayPanel dayPanel;
		for (int d = 0; d < 7; d++)
		{
			dayPanel = getDay(d);
			for (int m = 0; m < 3; m++)
				dayPanel.getMeal(m).setEditable(editable);
		}
		defaultSize();
		setLocationRelativeTo(null);
	}

	public OneDayPanel getDay(int day)
	{
		return days[day];
	}

	public String getSaveStr()
	{
		saveStr = "";
		for (int d = 0; d < 7; d++)
			saveStr = saveStr + days[d].getSaveStr();
		return saveStr;
	}

	@Override
	public void setBounds(int x, int y, int width, int height)
	{
		if (container == null || width < 200 || height < 200)
			return;
		if (width == getWidth() && height == getHeight())
		{
			super.setBounds(x, y, width, height);
			return;
		}
		updateSizeAndPosition(width, height);
		int w = container.getWidth(), h = container.getHeight() + 30;
		// if (w > width)
		width = w;
		// if (h > height)
		height = h;
		container.setLocation((width - w) / 2, 0);
		super.setBounds(x, y, width, height);
	}

	private void updateSizeAndPosition(int width, int height)
	{
		// System.out.println("updateSizeAndPosition");
		int h = (height - 35) / 4 - 5, w, yy = 0, xx;
		int hh = (h - 30) / 3;
		int ss = hh / 10;
		hh = hh - ss;
		int ww = (int) (hh / 0.88);
		int n = MainApp.maxChooseNum;
		int tw = ((width - 60) / 2 - 110) / n;
		if (tw < ww + ss)
		{
			ss = tw / 10;
			ww = tw - ss;
			hh = (int) (ww * 0.88);
		}
		positionConfiger.updatePramater(ww, hh, ss);

		w = 60 + (ww + ss) * n;
		if (editable)
			w += hh + ss;
		width = w * 2 + 60;
		h = 30 + (hh + ss) * 3 + ss;
		height = (h + 3) * 4;
		container.setSize(width, height);

		xx = w + 40;
		for (int i = 0; i < 4; i++)
		{
			days[i].setBounds(20, yy, w, h);
			if (i + 4 < 7)
				days[i + 4].setBounds(xx, yy, w, h);
			yy = yy + h + 3;
		}
		buttonPanel.setBounds(xx, yy - h - 3, w, h);

		int bwidth = 110;
		xx = (w - bwidth * 3) / 4;
		yy = (h - 80) / 3;
		if (editable)
		{
			int px = xx;
			openData.setBounds(px, yy, bwidth, 40);
			px += xx + bwidth;
			setRandomData.setBounds(px, yy, bwidth, 40);
			px += xx + bwidth;
			saveData.setBounds(px, yy, bwidth, 40);
		} else
			enableEdit.setBounds(w / 2 - 90, yy, 180, 40);

		xx = (w - 240) / 3;
		yy += 40 + yy;
		saveText.setBounds(xx, yy, 120, 40);
		saveExcel.setBounds(xx + xx + 120, yy, 120, 40);
	}

	public void setToRecommend(int[][][] favoriteDatas)
	{
		OneDayPanel dayPanel;
		OneMealPanel mealPanel;
		for (int d = 0; d < 7; d++)
		{
			dayPanel = getDay(d);
			for (int m = 0; m < 3; m++)
			{
				mealPanel = dayPanel.getMeal(m);
				mealPanel.setData(favoriteDatas[d * 3 + m]);
				mealPanel.updateMeal();
			}
		}
	}

	public void setToRandom()
	{
		OneDayPanel dayPanel;
		for (int d = 0; d < 7; d++)
		{
			dayPanel = getDay(d);
			dayPanel.assortFoodInThread();
			//			for (int m = 0; m < 3; m++)
			//			{
			//				dayPanel.getMeal(m).setToRandom();
			//			}
		}
	}

	public void writeDataToFile(File f)
	{
		if (f == null)
			return;
		try (DataOutputStream dos = new DataOutputStream(
				new FileOutputStream(f)))
		{
			OneDayPanel dayPanel;
			dos.writeInt(AppConfig.appVersion);
			for (int n : MainApp.breakfastNums)
				dos.writeInt(n);
			for (int n : MainApp.otherNums)
				dos.writeInt(n);
			for (int n : MainApp.cols)
				dos.writeInt(n);
			for (int d = 0; d < 7; d++)
			{
				dayPanel = getDay(d);
				for (int m = 0; m < 3; m++)
					dayPanel.getMeal(m).writeData(dos);
			}
			dos.close();
			HintWindow.showHint("保存成功！", this);
			return;
		} catch (Exception e)
		{
			e.printStackTrace();
			HintWindow.showHint("保存出错！", this);
		}
	}

	public void readDataFromFile(File f)
	{
		if (f == null)
			return;
		DataInputStream dis = null;
		OneDayPanel dayPanel;
		try
		{
			dis = new DataInputStream(new FileInputStream(f));
			int appVersion = dis.readInt();
			if (appVersion < 100)
			{
				dis.close();
				dis = new DataInputStream(new FileInputStream(f));
			} else if (appVersion < 305)
			{
				if (!dealWithNewData(dis, f))
					return;
			} else if (!dealWithNewData2(dis, f))
				return;
			for (int d = 0; d < 7; d++)
			{
				dayPanel = getDay(d);
				for (int m = 0; m < 3; m++)
					dayPanel.getMeal(m).readData(dis, appVersion);
			}
			dis.close();
		} catch (Exception e)
		{
			ROptionPane.showMessageDialog(this, "数据错误！", "提示!");
			e.printStackTrace();
			if (dis != null)
				try
				{
					dis.close();
				} catch (IOException e1)
				{
					e1.printStackTrace();
				}
			return;
		}
		for (int d = 0; d < 7; d++)
		{
			dayPanel = getDay(d);
			for (int m = 0; m < 3; m++)
				dayPanel.getMeal(m).updateMeal();
		}
	}

	private boolean dealWithNewData(DataInputStream dis, File f)
			throws IOException
	{
		int[] nums = MainApp.breakfastNums;
		int[] chooseNums = new int[nums.length];
		int[] cols = MainApp.cols;
		int[] columns = new int[cols.length];
		for (int i = 0; i < chooseNums.length; i++)
			chooseNums[i] = dis.readInt();
		for (int i = 0; i < columns.length; i++)
			columns[i] = dis.readInt();

		for (int i = 0; i < nums.length; i++)
			if (chooseNums[i] != nums[i] || columns[i] != cols[i])
			{
				dis.close();
				if (ROptionPane.showConfirmDialog(this, "数据不匹配！是否重启软件并重新打开？",
						"数据不匹配!") == 0)
				{
					for (int j = 0; j < chooseNums.length; j++)
						SettingTools.putDefaultSettingData(
								MainApp.bChooseNumsKey + j, chooseNums[j]);
					for (int j = 0; j < columns.length; j++)
						SettingTools.putDefaultSettingData(
								MainApp.columnKey + j, columns[j]);
					SettingTools.putDefaultSettingData("dataFilePath",
							f.getAbsolutePath());
					RLafUtils.restartApplication();
				}
				return false;
			}
		return true;
	}

	private boolean dealWithNewData2(DataInputStream dis, File f)
			throws IOException
	{
		int[] bNums = MainApp.breakfastNums;
		int[] bChooseNums = new int[bNums.length];
		int[] oNums = MainApp.otherNums;
		int[] oChooseNums = new int[oNums.length];
		int[] cols = MainApp.cols;
		int[] columns = new int[cols.length];
		for (int i = 0; i < bChooseNums.length; i++)
			bChooseNums[i] = dis.readInt();
		for (int i = 0; i < oChooseNums.length; i++)
			oChooseNums[i] = dis.readInt();
		for (int i = 0; i < columns.length; i++)
			columns[i] = dis.readInt();

		for (int i = 0; i < bNums.length; i++)
			if (bChooseNums[i] != bNums[i] || oChooseNums[i] != oNums[i]
					|| columns[i] != cols[i])
			{
				dis.close();
				if (ROptionPane.showConfirmDialog(this, "数据不匹配！是否重启软件并重新打开？",
						"数据不匹配!") == 0)
				{
					for (int j = 0; j < bChooseNums.length; j++)
						SettingTools.putDefaultSettingData(
								MainApp.bChooseNumsKey + j, bChooseNums[j]);
					for (int j = 0; j < bChooseNums.length; j++)
						SettingTools.putDefaultSettingData(
								MainApp.oChooseNumsKey + j, oChooseNums[j]);
					for (int j = 0; j < columns.length; j++)
						SettingTools.putDefaultSettingData(
								MainApp.columnKey + j, columns[j]);
					SettingTools.putDefaultSettingData("dataFilePath",
							f.getAbsolutePath());
					RLafUtils.restartApplication();
				}
				return false;
			}
		return true;
	}

	public MealLagerView getMealLagerView()
	{
		if (mealLagerView == null)
			mealLagerView = new MealLagerView(this);
		return mealLagerView;
	}

	public BreakfastEditer getBreakfastEditer()
	{
		if (breakfastEditer == null)
			breakfastEditer = new BreakfastEditer(this, true);
		return breakfastEditer;
	}

	public OtherMealEditer getOtherMealEditer()
	{
		if (otherMealEditer == null)
			otherMealEditer = new OtherMealEditer(this, true);
		return otherMealEditer;
	}

	public void updateSimpleExcelData()
	{
		simpleExcelData.clear();
		int index = 0;
		for (OneDayPanel day : days)
		{
			index = day.updateSimpleExcelData(index);
		}
	}

	public void updateCustomExcelData()
	{
		customExcelData.clear();
		int index = 0;
		for (OneDayPanel day : days)
		{
			index = day.updateCustomExcelData(index);
		}
	}

	private class SaveOperator1 implements Operator
	{
		RFileChooser txtSaveChooser = null;
		@Override
		public void operate(Object o)
		{
			if (txtSaveChooser == null)
			{
				txtSaveChooser = new RFileChooser(MainApp.getOutputFolder(),
						"txt", "导出为TXT文件");
				txtSaveChooser
						.setDialogSymbol(new ScaleImageComp(Resource.textIcon));
			}
			File file = txtSaveChooser.openAndGetSaveFile(OneWeekView.this);
			if (file != null)
			{
				TextTools.writeTxtFile(file, getSaveStr());
				SystemTools.openFile(file);
			}
		}
	}

	private class SaveOperator3 implements Operator
	{
		RFileChooser xlsSaveChooser = null;
		@Override
		public void operate(Object o)
		{
			if (xlsSaveChooser == null)
			{
				xlsSaveChooser = new RFileChooser(MainApp.getOutputFolder(),
						"xls", "导出为XLS文件");
				xlsSaveChooser.setDialogSymbol(
						new ScaleImageComp(Resource.excelIcon));
			}
			File file = xlsSaveChooser.openAndGetSaveFile(OneWeekView.this);
			if (file == null)
				return;
			File templateFile = FileTools.getUserFile("excel/customTemplate.xls");
			if (!templateFile.isFile())
				templateFile = FileTools.getUserFile("excel/customTemplate.xlsx");

			InputStream templateInput;
			Map<String, String> data;
			try
			{
				templateInput = new FileInputStream(templateFile);
				updateCustomExcelData();
				data = customExcelData;
			} catch (IOException e)
			{
				templateInput = FileTools.getInputStream(Resource.class,
						"shipu.xls");
				updateSimpleExcelData();
				data = simpleExcelData;
			}
			ExcelUtils.getInstance().exportSimpleMap2Excel(templateInput, data, file);
			SystemTools.openFile(file);
		}
	}

	private class SaveDataOperator implements Operator
	{
		RFileChooser saveChooser = null;
		@Override
		public void operate(Object o)
		{
			if (saveChooser == null)
				saveChooser = new RFileChooser(MainApp.getFoodDataForder(),
						"sdata", "保存食谱数据");
			File file = saveChooser.openAndGetSaveFile(OneWeekView.this);
			if (file != null)
			{
				writeDataToFile(file);
			}
		}
	}

	private class OpenDataOperator implements Operator
	{
		RFileChooser openChooser = null;
		@Override
		public void operate(Object o)
		{
			if (openChooser == null)
				openChooser = new RFileChooser(MainApp.getFoodDataForder(),
						"sdata", "打开食谱数据");
			File file = openChooser.openAndGetOpenFile(OneWeekView.this);
			if (file != null)
			{
				readDataFromFile(file);
			}
		}
	}
}
